#include "main.h"
#include <stdint.h>

LIN_MSG*  pSignalMsg;   //主机接收信号消息
LIN_MSG*  pWiperMsg; 
LIN_ERROR_Code  LIN_Err;
int Temp; 
int Temp2;  
static uint8_t LIN_SendFlg;
extern LIN_BUFFER    LIN_RxDataBuff;
extern uint8_t WiperCondata; 

void Wiper_Drive(LIN_MSG *pMsg);

int main(void)	
{

	HardWareInit();   //外设初始化
	OLED_ShowInit();  //OLED初始化显示
	LIN_IDTypeConfig(); //LIN_ID类型配置
	
	while (1)
	{
		 //uint8_t KeyNum = KeyGetNum(0); //扫描按键状态  	    
		 if (LIN_SendFlg){    //LIN信号消息 50ms定时发送
			Wiper_Drive(pWiperMsg);			 
			LIN_SendMsg(USART1, 0x32, NULL, 8, FrameIDType[0x32]);//主机读			 
			LIN_SendMsg(USART1, 0x31, pWiperMsg->Data, 8, FrameIDType[0x31]);//主机写
			LIN_SendFlg = 0;			 
		 }				 
	  	 LIN_Err = LIN_Process(&LIN_RxDataBuff);//LIN协议校验
		 LIN_ErrorCode(LIN_Err);  //LIN错误显示 					
//		 if ((LIN_Err==LIN_OK)&&(pSignalMsg!=NULL)){	  //主机接收任务处理				
//			LIN_LED_Drive(pSignalMsg);
//		 }
	}
} 	


static uint8_t LIN_GetSendFlg(void)
{
	static uint16_t Num = 0; 	
	if (!LIN_SendFlg){
		Num++; 
	}
	if (Num >= 50){	
		Num = 0;
		return 1;
	}else{
		return 0;
	}	
}

//LIN定时发送
void TIM2_IRQHandler(void)
{	
	if (TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){//定时器更新中断
		LIN_SendFlg = LIN_GetSendFlg();
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);  //清除更新中断标志位						
	}		
}

void HardWareInit(void)
{
	//设置中断优先级分组为2
	//两位抢占优先级(取值：0 ~ 3)、两位响应优先级(取值：0 ~ 3)  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 
	
	LED_Init();							//LED初始化
	Key_Init();							//按键初始化	
	Temp = USART1_Init(19200);   //串口1初始化:波特率19200
	Temp = 12*10000/Temp;
	Temp2 = Temp;
	USART2_Init(19200);
	TIM3_Init();						//定时器初始化
	TIM4_Init();						//定时器初始化
	TIM2_Init();						//LIN定时发送
	OLED_Init();						//OLED初始化
}

void OLED_ShowInit(void)
{
	//OLED显示主机读、写ID
//	OLED_ShowString(1,1,"31:");  //主机写ID
//	OLED_ShowString(3,1,"32:");  //主机读ID	
	OLED_ShowString(1,1,"LErr:");  //主机读ID	
}

void LIN_IDTypeConfig(void)
{
	//LIN主机ID类型配置(所有ID默认初始化为MASTER_BREAK)
	FrameIDType[0x31] = MASTER_WRITE; 
	FrameIDType[0x32] = MASTER_READ;  	
 	
}

void OLED_MASTER_WData(void)
{
	//LIN主机发送数据(帧ID：0x31)		
	OLED_ShowHexNum(1,5,pWiperMsg->Data[0],2);
	OLED_ShowHexNum(1,8,pWiperMsg->Data[1],2);	
	OLED_ShowHexNum(1,11,pWiperMsg->Data[2],2);	
	OLED_ShowHexNum(1,14,pWiperMsg->Data[3],2);
	OLED_ShowHexNum(2,5,pWiperMsg->Data[4],2);
	OLED_ShowHexNum(2,8,pWiperMsg->Data[5],2);	
	OLED_ShowHexNum(2,11,pWiperMsg->Data[6],2);	  
	OLED_ShowHexNum(2,14,pWiperMsg->Data[7],2);	

	//LIN主机接收数据(帧ID：0x32)	
	OLED_ShowHexNum(3,5,pSignalMsg->Data[0],2);
	OLED_ShowHexNum(3,8,pSignalMsg->Data[1],2);	
	OLED_ShowHexNum(3,11,pSignalMsg->Data[2],2);	
	OLED_ShowHexNum(3,14,pSignalMsg->Data[3],2);	
	
	OLED_ShowHexNum(4,5,pSignalMsg->Data[4],2);
	OLED_ShowHexNum(4,8,pSignalMsg->Data[5],2);	
	OLED_ShowHexNum(4,11,pSignalMsg->Data[6],2);	
	OLED_ShowHexNum(4,14,pSignalMsg->Data[7],2);	
}

//主机接收驱动LED
void LIN_LED_Drive(LIN_MSG* pLINMsg)
{	
	if (pLINMsg->FrameID == 0x02){
		switch (pLINMsg->Data[0]){		
			case 0x00:
				GPIO_SetBits(GPIOC,GPIO_Pin_13);	    //熄灭LED						
			break;
			case 0x01:	
				GPIO_ResetBits(GPIOC,GPIO_Pin_13);	    //点亮LED						
			break;				
		}		
	}
}



/**
  * @brief  刮水器控制
  * @param  None
  * @retval None
  */
void Wiper_Drive(LIN_MSG *pMsg)
{
	static uint8_t Auto_Resetflg =  0;//刮水器点动档位自动复位标志
	static uint8_t Auto_Resetflg2 = 0;//刮水器档位控制位制动复位标志2
	static uint8_t TimOut = 0;        //刮水器档位自动复位超时计数	
	static uint8_t temp = 1;	      //刮水器间歇档间歇等级控制变量
	static uint8_t Turnflg = 0;       //间歇档间歇等级翻转标志

	switch (WiperCondata){
		/*《车辆状态控制/点火开关信号位》
		 * pMsg->Data[0](位：7~0；共8位)= xx00 xxxx(位5~4为车辆状态控制位), 位x与该信号无关
		 * 点火开关关闭：xx00 xxxx 
		 * 点火开关开启：xx11 xxxx     (车辆未启动)
		 * 车辆启动中：  xx01 xxxx     (雨刮器不能动作)	
		 * 车辆已启动：  xx?? xxxx     (待解析)
		 */
		//车辆状态(点火开关)控制		
		case 0x01:{	
			if ((pMsg->Data[0] &  (0x03<<4)) == 0){				 
				 pMsg->Data[0] &= (~(0x03<<4));
				 pMsg->Data[0] |= (0x03<<4); //开启点火开关
			}else{			
				 pMsg->Data[0] &= (~(0x03<<4));  //关闭点火开关	
			}
		}break;		
		 /*《引擎盖状态控制信号位》
		  * pMsg->Data[0](位：7~0；共8位)= 0xxx xxxx(位：7为引擎盖位置状态控制位), 位x与该信号无关 
		  * 引擎盖状态关闭：0xxx xxxx 
		  * 引擎盖状态开启：1xxx xxxx 
		  */
		case 0x02:{
			if ((pMsg->Data[0] &  (0x01<<7)) == 0){
				 pMsg->Data[0] &= (~(0x01<<7));
				 pMsg->Data[0] |= (0x01<<7);     //开启引擎盖	
			}else{
				 pMsg->Data[0] &= (~(0x01<<7));  //关闭引擎盖
			}
		}break;		
		/*《刮水器间歇档间歇等级信号控制位》(新方法)
		 * pMsg->Data[1](位：7~0；共8位) = xxxx 0000(位：3~0为刮水器间歇档间歇等级控制位), x位与该信号无关	
		 * 间歇等级：1级：xxxx 0001 (0x1)
		 *           2级：xxxx 0101 (0x5)	
		 *           3级：xxxx 1001 (0x9)
		 *           4级：xxxx 1101 (0xD)
		 * 注：该档位只在刮水器控制开关处于间歇档时有效。间歇等级越高，间歇档间歇时间越短 
		 */
		case 0x03:{
			temp += Turnflg == 0 ? 4 : -4; 
			if (temp > 0x0D){
				Turnflg = 1;
				temp = 0x09;
			}else if (temp <= 0x01){
				Turnflg = 0;						
			}
			pMsg->Data[1] &= (0x0F << 4);
			pMsg->Data[1] |= temp;				
		}break;
		/*《刮水器档位控制》
		 * pMsg->Data[1](位：7~0；共8位)= 0000 xxxx(位：7~4为刮水器档位控制位), x位与该信号无关
		 * 1、OFF档：     0000 xxxx
		 * 2、点动档位：  0001 xxxx  (刮水器只动作1次)	   
		 * 3、间歇档位：  0010 xxxx
		 * 4、自动挡低速：0100 xxxx
		 * 5、自动挡高速：1000 xxxx 
		 */
		//点动档控制
		case 0x04: {
			//设置刮水器点动档位自动复位标志
			Auto_Resetflg = 1; 			
			//操作刮水器档位控制位(位：8 ~ 5)
			pMsg->Data[1] &= (~(0x0F<<4));
			pMsg->Data[1] |= (0x01<<4);	   //点动档(自动复位)	
		}break;
		//间歇档控制
		case 0x05:{
			//检查刮水器间歇档控制位
			if ((pMsg->Data[1] & (0x01<<5)) == 0x20){
				//操作刮水器档位控制位(位：7~4)
				pMsg->Data[1] &= (~(0x0F<<4));
				pMsg->Data[1] |= (0x01<<5);     //间歇档						
			}else{
				pMsg->Data[1] &= (~(0x0F<<4));  //OFF档				
			}		
		}break;		
		//自动挡控制：低速档(Low)		
		case 0x06:{
			//检查低速档是否关闭
			if ((pMsg->Data[1] & (0x01<<6)) == 0x40){
				//操作刮水器档位控制位(位：7~4)
				pMsg->Data[1] &= (~(0x0F<<4));
				pMsg->Data[1] |= (0x01<<6);	//自动低速档		
			}else{
				pMsg->Data[1] &= (~(0x0F<<4));			
			}				
		}break;		
		//自动挡控制：高速档(High)		
		case 0x07:{
			//检查刮水器自动挡控制位高速High是否关闭
			if ((pMsg->Data[1] & (0x01<<7)) == 0x80){
				//操作刮水器档位控制位(位：7~4)
				pMsg->Data[1] &= (~(0x0F<<4));
				pMsg->Data[1] |= (0x01<<7);	 //自动高速档						
			}else{
				pMsg->Data[1] &= (~(0x0F<<4)); //OFF档					
			}		
		}break;
		//维修模式
		case 0x08:{
			Auto_Resetflg = 1;
			pMsg->Data[0] &= 0xCF;
			
			pMsg->Data[1] &= 0x0F;  //OFF档
			pMsg->Data[1] |= 0x10;	//点动档		

			pMsg->Data[2] = 0x06;
			pMsg->Data[3] = 0x8F;			
		}break;
		//清洗档
		case 0x09:{
			Auto_Resetflg2 = 1;  //清洗档自动复位标志
			pMsg->Data[2] &= 0xF0;
			pMsg->Data[2] |= 0x05;
			pMsg->Data[2] &= 0x0F;
			pMsg->Data[2] |= 0x90;  //洗涤电机动作			
		}break;
		default: 
			break;		
	} /* swtich */
					
	if (Auto_Resetflg){
		//自动复位计数自增
		TimOut++; 
		//循环15次后自动关闭刮水器档位控制位
		if (TimOut >= 15){
			TimOut = 0; 
			Auto_Resetflg = 0;			
			//操作刮水器档位控制位(位：8 ~ 5)
			pMsg->Data[1] &= (~(0x0F<<4));  //OFF档	
			pMsg->Data[2] = 0x04;   //维修模式数据复位
			pMsg->Data[3] = 0xAF;			
		}
	}
    //软件自动清除按键标志	
	if (Auto_Resetflg2){
		TimOut++;
		if (TimOut >= 50){
			TimOut = 0;
			Auto_Resetflg2 = 0;
			pMsg->Data[2] &= 0xF0;
			pMsg->Data[2] |= 0x04;			
		}
	}
	WiperCondata = 0;		
	
}














